tags:
- SQL视图是虚拟的
Materialized View 物化视图

JOIN command in SQL to combine rows from two or more tables based on a related column between them. Here is a visual representation of how these tables could be joined in order to line up authors and their books.
This makes it simple to observe that Han Kang authored The White Book.
longlist.db on SQLite and run the .schema command to verify that the three tables we saw in the previous example are created: authors, authored and books.SELECT "title" FROM "books"
WHERE "id" IN (
SELECT "book_id" FROM "authored"
WHERE "author_id" = (
SELECT "id" FROM "authors"
WHERE "name" = 'Fernanda Melchor'
)
);
SELECT queries in the nested query. To simplify this, let us first use JOIN to create a view containing authors and their books.longlist.db again, and run the following query.
SELECT "name", "title" FROM "authors"
JOIN "authored" ON "authors"."id" = "authored"."author_id"
JOIN "books" ON "books"."id" = "authored"."book_id";
CREATE VIEW "longlist" AS
SELECT "name", "title" FROM "authors"
JOIN "authored" ON "authors"."id" = "authored"."author_id"
JOIN "books" ON "books"."id" = "authored"."book_id";
The view created here is called longlist. This view can now be used exactly as we would use a table in SQL.SELECT * FROM "longlist";
SELECT "title" FROM "longlist" WHERE "name" = 'Fernanda Melchor';
Can we manipulate views to be ordered, or displayed differently?
longlist view, ordered by the book titles.
SELECT "name", "title"
FROM "longlist"
ORDER BY "title";
ORDER BY clause in the query used to create the view.也就是创建视图的时候就进行排序longlist.db we have a table containing individual ratings given to each book. In previous weeks, we saw how to find the average rating of every book, rounded to 2 decimal places.
SELECT "book_id", ROUND(AVG("rating"), 2) AS "rating"
FROM "ratings"
GROUP BY "book_id";
books table.
SELECT "book_id", "title", "year", ROUND(AVG("rating"), 2) AS "rating"
FROM "ratings"
JOIN "books" ON "ratings"."book_id" = "books"."id"
GROUP BY "book_id";
JOIN to combine information from the ratings and books tables, joining on the book ID column.GROUP BY operation at the end of the query after the two tables are joined.CREATE VIEW "average_book_ratings" AS
SELECT "book_id" AS "id", "title", "year", ROUND(AVG("rating"), 2) AS "rating"
FROM "ratings"
JOIN "books" ON "ratings"."book_id" = "books"."id"
GROUP BY "book_id";
SELECT * FROM "average_book_ratings";
ratings table, to obtain an up-to-date aggregate, we need to simply requery the view using a SELECT command like the above!.schema to observe that longlist and average_book_ratings are now part of this database’s schema.CREATE TEMPORARY VIEW. This command creates a view that exists only for the duration of our connection with the database.SELECT "year", ROUND(AVG("rating"), 2) AS "rating"
FROM "average_book_ratings"
GROUP BY "year";
Notice that we select the rating column from average_book_ratings, which already contains the average ratings per book. Next, we group these by year and calculate the average ratings again, which gives us the average rating per year!CREATE TEMPORARY VIEW "average_ratings_by_year" AS
SELECT "year", ROUND(AVG("rating"), 2) AS "rating" FROM "average_book_ratings"
GROUP BY "year";
.quit之后,在进入sqlite3,就不能够用 temp view 了
Can temporary views be used to test whether a query works or not?
average_book_ratings.
DROP VIEW "average_book_ratings";
WITH "average_book_ratings" AS (
SELECT "book_id", "title", "year", ROUND(AVG("rating"), 2) AS "rating" FROM "ratings"
JOIN "books" ON "ratings"."book_id" = "books"."id"
GROUP BY "book_id"
)
SELECT "year" ROUND(AVG("rating"), 2) AS "rating" FROM "average_book_ratings"
GROUP BY "year";
CREATE VIEW "2022" AS
SELECT "id", "title" FROM "books"
WHERE "year" = 2022;
SELECT * FROM "2022";
Can views be updated?
cannot modify the data in the view
rides that looks like the following.

rideshare.db in our terminal. Running .schema should reveal one table called rides in this database.rider column altogether. But we will go one step further here, and create a rider column to display an anonymous rider for each row in the table. This will indicate to the analyst that while we have rider names in the database, the names have been anonymized for security.
CREATE VIEW "analysis" AS
SELECT "id", "origin", "destination", 'Anonymous' AS "rider"
FROM "rides";
SELECT * FROM "analysis";
rides table and see all the rider names we went to great lengths to omit in the analysis view.collections table by changing the value in the deleted column from 0 to 1.

mfa.db in our terminal. The collections table does not have a deleted column yet, so we need to add it. The default value here will be 0, to indicate that the row is not deleted.
ALTER TABLE "collections"
ADD COLUMN "deleted" INTEGER DEFAULT 0;
deleted column.
UPDATE "collections"
SET "deleted" = 1
WHERE "title" = 'Farmers working at dawn';
CREATE VIEW "current_collections" AS
SELECT "id", "title", "accession_number", "acquired"
FROM "collections"
WHERE "deleted" = 0;
SELECT * FROM "current_collections";
collections, it will be removed from the current_collections view on any further querying.INSTEAD OF trigger allows us to do this.
CREATE TRIGGER "delete"
INSTEAD OF DELETE ON "current_collections"
FOR EACH ROW
BEGIN
UPDATE "collections" SET "deleted" = 1
WHERE "id" = OLD."id";
END;
deleted column of the row in the underlying table collections, thus completing the soft deletion.OLD within our update clause to indicate that the ID of the row updated in collections should be the same as the ID of the row we are trying to delete from current_collections.current_collections view.
DELETE FROM "current_collections"
WHERE "title" = 'Imaginative landscape';
We can verify that this worked by querying the view.
SELECT * FROM "current_collections";
CREATE TRIGGER "insert_when_exists"
INSTEAD OF INSERT ON "current_collections"
FOR EACH ROW
WHEN NEW."accession_number" IN (
SELECT "accession_number" FROM "collections"
)
BEGIN
UPDATE "collections"
SET "deleted" = 0
WHERE "accession_number" = NEW."accession_number";
END;
WHEN keyword is used to check if the accession number of the artwork already exists in the collections table. This works because an accession number, as we know from previous weeks, uniquely identifies every piece of art in this table.deleted value to 0, indicating a reversal of the soft deletion.CREATE TRIGGER "insert_when_new"
INSTEAD OF INSERT ON "current_collections"
FOR EACH ROW
WHEN NEW."accession_number" NOT IN (
SELECT "accession_number" FROM "collections"
)
BEGIN
INSERT INTO "collections" ("title", "accession_number", "acquired")
VALUES (NEW."title", NEW."accession_number", NEW."acquired");
END;
collections, it inserts the row into the table.